package com.och.mrcp.core.rtp.session;

import com.och.mrcp.core.rtp.model.RtpPacket;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * RTP包发送器
 * 负责实际的UDP网络传输
 */
@Slf4j
public class RtpSender {
    
    private final InetSocketAddress localAddress;
    private final InetSocketAddress remoteAddress;
    private DatagramSocket udpSocket;
    private final AtomicBoolean isActive = new AtomicBoolean(false);
    
    // 统计信息
    private final AtomicLong packetsSent = new AtomicLong(0);
    private final AtomicLong bytesSent = new AtomicLong(0);
    private final AtomicLong sendErrors = new AtomicLong(0);
    
    public RtpSender(InetSocketAddress localAddress, InetSocketAddress remoteAddress) {
        this.localAddress = localAddress;
        this.remoteAddress = remoteAddress;
    }
    
    /**
     * 启动RTP发送器
     */
    public synchronized void start() throws SocketException {
        if (isActive.get()) {
            log.warn("RTP sender already started for {}", remoteAddress);
            return;
        }
        
        try {
            // 创建UDP Socket - 不绑定特定端口，让系统自动分配
            // 这样可以避免与RTP接收器的端口冲突
            udpSocket = new DatagramSocket();
            
            // 设置Socket选项
            udpSocket.setSendBufferSize(64 * 1024); // 64KB发送缓冲区
            udpSocket.setReuseAddress(true);
            
            isActive.set(true);
            log.info("RTP sender started: {} -> {}", udpSocket.getLocalSocketAddress(), remoteAddress);
            
        } catch (SocketException e) {
            log.error("Failed to start RTP sender: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 停止RTP发送器
     */
    public synchronized void stop() {
        if (!isActive.get()) {
            return;
        }
        
        isActive.set(false);
        
        if (udpSocket != null && !udpSocket.isClosed()) {
            udpSocket.close();
            log.info("RTP sender stopped for {}", remoteAddress);
        }
    }
    
    /**
     * 发送RTP包
     */
    public void sendPacket(RtpPacket packet) throws IOException {
        if (!isActive.get()) {
            throw new IllegalStateException("RTP sender is not active");
        }
        
        if (udpSocket == null || udpSocket.isClosed()) {
            throw new IllegalStateException("UDP socket is not available");
        }
        
        try {
            // 编码RTP包
            byte[] packetData = packet.encode();
            
            // 创建UDP数据包
            DatagramPacket udpPacket = new DatagramPacket(
                packetData, 
                packetData.length, 
                remoteAddress
            );
            
            // 发送UDP包
            udpSocket.send(udpPacket);
            
            // 更新统计信息
            packetsSent.incrementAndGet();
            bytesSent.addAndGet(packetData.length);
            
            log.debug("RTP packet sent: seq={}, timestamp={}, size={} bytes to {}", 
                    packet.getSequenceNumber(), packet.getTimestamp(), 
                    packetData.length, remoteAddress);
            
        } catch (IOException e) {
            sendErrors.incrementAndGet();
            log.error("Failed to send RTP packet to {}: {}", remoteAddress, e.getMessage());
            throw e;
        }
    }
    
    /**
     * 批量发送RTP包（用于减少系统调用开销）
     */
    public void sendPackets(RtpPacket[] packets) throws IOException {
        if (packets == null || packets.length == 0) {
            return;
        }
        
        for (RtpPacket packet : packets) {
            if (packet != null) {
                sendPacket(packet);
            }
        }
    }
    
    /**
     * 获取本地地址
     */
    public InetSocketAddress getLocalAddress() {
        if (udpSocket != null && !udpSocket.isClosed()) {
            return (InetSocketAddress) udpSocket.getLocalSocketAddress();
        }
        return localAddress;
    }
    
    /**
     * 获取远程地址
     */
    public InetSocketAddress getRemoteAddress() {
        return remoteAddress;
    }
    
    /**
     * 检查发送器是否活跃
     */
    public boolean isActive() {
        return isActive.get() && udpSocket != null && !udpSocket.isClosed();
    }
    
    /**
     * 获取发送统计信息
     */
    public RtpSenderStats getStats() {
        RtpSenderStats stats = new RtpSenderStats();
        stats.setLocalAddress(getLocalAddress());
        stats.setRemoteAddress(remoteAddress);
        stats.setPacketsSent(packetsSent.get());
        stats.setBytesSent(bytesSent.get());
        stats.setSendErrors(sendErrors.get());
        stats.setActive(isActive.get());
        return stats;
    }
    
    /**
     * RTP发送器统计信息
     */
    public static class RtpSenderStats {
        private InetSocketAddress localAddress;
        private InetSocketAddress remoteAddress;
        private long packetsSent;
        private long bytesSent;
        private long sendErrors;
        private boolean active;
        
        // Getters and setters
        public InetSocketAddress getLocalAddress() { return localAddress; }
        public void setLocalAddress(InetSocketAddress localAddress) { this.localAddress = localAddress; }
        
        public InetSocketAddress getRemoteAddress() { return remoteAddress; }
        public void setRemoteAddress(InetSocketAddress remoteAddress) { this.remoteAddress = remoteAddress; }
        
        public long getPacketsSent() { return packetsSent; }
        public void setPacketsSent(long packetsSent) { this.packetsSent = packetsSent; }
        
        public long getBytesSent() { return bytesSent; }
        public void setBytesSent(long bytesSent) { this.bytesSent = bytesSent; }
        
        public long getSendErrors() { return sendErrors; }
        public void setSendErrors(long sendErrors) { this.sendErrors = sendErrors; }
        
        public boolean isActive() { return active; }
        public void setActive(boolean active) { this.active = active; }
        
        @Override
        public String toString() {
            return String.format("RtpSenderStats{local=%s, remote=%s, sent=%d packets/%d bytes, errors=%d, active=%s}",
                    localAddress, remoteAddress, packetsSent, bytesSent, sendErrors, active);
        }
    }
}
